﻿using System;
using System.Collections.Generic;
using System.Text;
using Kitware.VTK;

namespace Fu3DEngine
{
    public  class TerrainScene:SceneBase 
    {
        public TerrainScene(string id):base(id)
        { 
        }

        TerrainData m_tData;

        //public override  bool CreateScene(SceneData data)
        //{
        //    return true;
        //}

        public   override void Run()
        {
            //在这之前，先把m_tData搞定，因为他要在后面的普通对象中使用

            

            base.Run();
        }

        public virtual  void CreateTerrainFromDem()
        {
 
        }

        public void CreateTerrainFromBox()
        {
           

 
        }


        //定义一些内部算法方法
        //dem全球米为单位的坐标，转换为格子点坐标
        protected DPoint PointToGridPoint(DPoint point)
        {
            double x = point.x - org[0];
            double y = point.y - org[1];

            x = x / m_spatialResolution[0];
            y = y / m_spatialResolution[1];

            return new DPoint(x, y);

        }

        double[] org;
        int rows;
        int cols;
        int hUnit;//垂直方向的单位类型
        int wUnit; //表示水平方向的单位类型
        float minHeight;
        float maxHeight;
        float[] m_spatialResolution;

        double m_scalefactor = 1;


        public TerrainData CreateTerrain(string strDem, string pfilename, double wsPointX, double wsPointY, double enPointX, double enPointY)
        {
            // Create components of the rendering subsystem
            //

           





            vtkDEMReader dem = vtkDEMReader.New();
            dem.SetFileName(strDem);

            dem.SetElevationReferenceToElevationBounds();

            dem.Update();
            hUnit = dem.GetElevationUnitOfMeasure();
            wUnit = dem.GetPlaneUnitOfMeasure();
            float[] elev = dem.GetElevationBounds();
            minHeight = elev[0];
            maxHeight = elev[1];

            m_spatialResolution = dem.GetSpatialResolution();






            vtkImageData demImage;
            demImage = dem.GetOutput();
            double[] space = demImage.GetSpacing();
            int[] dim = demImage.GetDimensions();
            rows = dim[0];
            cols = dim[1];


            //WGS84原点的坐标
            org = demImage.GetOrigin();




            //vtkImageShiftScale iss = vtkImageShiftScale.New();
            //iss.SetInput(dem.GetOutput());

            //iss.SetOutputScalarTypeToUnsignedChar();


            //vtkImageActor iActor = vtkImageActor.New();
            //iActor.SetInput(iss.GetOutput());








            //主地形的添加

            vtkImageDataGeometryFilter gemo = vtkImageDataGeometryFilter.New();
            gemo.SetInput(dem.GetOutput());
            gemo.OutputTrianglesOn();


            vtkWarpScalar m_warp = vtkWarpScalar.New();
            m_warp.SetInput(gemo.GetOutput());

            m_warp.SetScaleFactor(m_scalefactor);
            m_warp.SetNormal(0, 0, 1);
            m_warp.UseNormalOn();

            m_warp.Update();










            double[] temp = dem.GetOutput().GetScalarRange();
            double lo = temp[0];
            double hi = temp[1];


            vtkLookupTable lut = vtkLookupTable.New();
            lut.SetHueRange(0.6, 0);
            lut.SetSaturationRange(1, 0);
            lut.SetValueRange(0.5, 1);


            vtkPolyDataNormals normal = vtkPolyDataNormals.New();
            normal.SetInput(m_warp.GetOutput());
            normal.SetFeatureAngle(60);
            normal.SplittingOff();




            //主地形的切分

            vtkPolyData pData = normal.GetOutput();



            vtkBox box = vtkBox.New();
            box.SetXMin(wsPointX, wsPointY, minHeight);
            box.SetXMax(enPointX, enPointY, maxHeight);


            vtkClipPolyData clip = vtkClipPolyData.New();
            clip.SetInput(pData);
            clip.SetClipFunction(box);
            clip.GenerateClippedOutputOn();


            //添加边框地形
            vtkPolyDataMapper boundMapper = vtkPolyDataMapper.New();
            boundMapper.SetInput(clip.GetOutput());
            boundMapper.SetLookupTable(lut);
            boundMapper.SetScalarRange(lo, hi);

            vtkActor boundActor = vtkActor.New();
            boundActor.SetMapper(boundMapper);
            boundActor.PickableOn();

            m_vtkRenderer.AddActor(boundActor);



            double[] bounds = boundActor.GetBounds();

           // m_ActorDic.Add("boundActor", boundActor);





            //添加网格地形
            vtkPolyDataMapper gridMapper = vtkPolyDataMapper.New();
            gridMapper.SetInput(clip.GetClippedOutput());

            gridMapper.SetLookupTable(lut);
            gridMapper.SetScalarRange(lo, hi);
            gridMapper.ScalarVisibilityOff();



            //为网格地形，准备污染贴图

            //vtkImageReader2 imgReader = vtkImageReader2Factory.CreateImageReader2(pfilename);
            //imgReader.SetFileName(pfilename);
            //imgReader.Update();





            //vtkTexture texSun =  vtkTexture.New();
            //texSun.SetInput(imgReader.GetOutput());

            //texSun.InterpolateOn();


            //vtkTextureMapToPlane tmt =  vtkTextureMapToPlane.New();
            //tmt.SetInputConnection(clip.GetClippedOutputPort());
            //tmt.AutomaticPlaneGenerationOn();



            //tmt.Update();






            /*    真是太他妈的长了、、、*/


            #region 这里是为了计算方图，真想吐血




            //在能够精确计算与污染图对应关系之前，先使用自定义的正方形
            //下面计算一个抽取正方形的算法
            int length;
            int extpart;
            int elength;//正方形的边长
            int a, b, c, d;

            if (rows > cols)
            {
                length = cols;
                extpart = (rows - cols) / 2;
                a = 20;
                b = cols - 20;
                c = 20 + extpart;
                d = rows - 20 - extpart;

                elength = cols - 40;

            }
            else
            {
                length = rows;
                extpart = cols - rows;

                a = 20 + extpart;
                b = cols - 20 - extpart;
                c = 20;
                d = rows - 20;

                elength = rows - 40;
            }

            DPoint wsPoint = new DPoint(wsPointX, wsPointY);
            DPoint enPoint = new DPoint(enPointX, enPointY);

            DPoint pws = PointToGridPoint(wsPoint);
            DPoint pen = PointToGridPoint(enPoint);









            //纹理部分所作的测试

            //为网格地形，准备污染贴图
            vtkImageReader2 imgReader = vtkImageReader2Factory.CreateImageReader2(pfilename);
            imgReader.SetFileName(pfilename);
            imgReader.Update();






            vtkImageChangeInformation ici = new vtkImageChangeInformation();

            ici.SetInput(imgReader.GetOutput());





            ici.CenterImageOn();

            vtkImageData img = new vtkImageData();
            img = imgReader.GetOutput();




            int[] dimen = img.GetDimensions();


            double scalex = 1, scaley = 1;
            int subX = 0, subY = 0;
            int idimenX = dimen[0];
            int idimenY = dimen[1];
            int idimen = dimen[0];
            if (dimen[0] != dimen[1])
            {
                if (dimen[0] > dimen[1])
                {
                    scaley = (double)dimen[0] / (double)dimen[1];
                    subX = (dimen[0] - dimen[1]) / 2 + 1;

                    idimen = dimen[0];
                    // subY = (dimen[0] - dimen[1]) / 2 + 1;
                    //subY = subX * 10;


                }
                else
                {
                    scalex = (double)dimen[1] / (double)dimen[0];
                    subY = (dimen[1] - dimen[0]) / 2 + 1;

                    idimen = dimen[1];
                    //subX = (dimen[1] - dimen[0]) / 2 + 1;

                }
            }

            vtkTransform trans2 = new vtkTransform();
            trans2.Scale(scaley, scalex, 1);

            vtkImageReslice slice2 = new vtkImageReslice();
            slice2.SetInput(ici.GetOutput());
            slice2.InterpolateOn();
            slice2.SetResliceTransform(trans2);



            vtkTransform trans = new vtkTransform();
            trans.RotateX(0);
            trans.RotateY(0);
            trans.RotateZ(270);
            // trans.Scale(scalex, scaley, 1);




            vtkImageReslice slice = new vtkImageReslice();
            slice.SetInput(slice2.GetOutput());
            //slice.SetInput(ici.GetOutput());

            slice.SetResliceTransform(trans);
            slice.InterpolateOn();
            slice.BorderOff();
            slice.SetInterpolationModeToCubic();


            vtkExtractVOI vo2 = new vtkExtractVOI();

            vo2.SetInput(slice.GetOutput());


            vo2.SetVOI(subX, idimen - subX, subY, idimen - subY, 0, 0);
            //vo2.SetVOI(subX, idimenX - subX, subY, idimenY - subY, 0, 0);

            vo2.SetSampleRate(1, 2, 3);
            vo2.Update();

            //vtkImageActor actor2 = new vtkImageActor();
            //actor2.SetInput(slice2.GetOutput());
            //actor2.SetPosition(OrignX, OrignY, OrignZ);
            //actor2.SetScale(10, 10, 1);
            //m_renderer.AddActor2D(actor2);


            vtkTexture texSun = new vtkTexture();
            texSun.SetInput(vo2.GetOutput());
            //texSun.SetInput(slice.GetOutput());
            //texSun.SetInput(jpgReader.GetOutput());
            texSun.InterpolateOn();


















            vtkTextureMapToPlane tmt = new vtkTextureMapToPlane();
            tmt.SetInputConnection(clip.GetClippedOutputPort());
            tmt.AutomaticPlaneGenerationOn();


            tmt.SetSRange(0, 0.992);//这里的作用是让非正方形的贴图能够拉伸显示
            tmt.SetTRange(0.015, 0.975);//这个VTK计算纹理坐标的数，真是让人头疼，真想卖了它，没办法，尽量用方形或者类似方形图吧



            vtkTransformTextureCoords xform = new vtkTransformTextureCoords();
            xform.SetInputConnection(tmt.GetOutputPort());

            xform.SetScale(1, 1, 1);
            xform.FlipSOn();




            #endregion


            gridMapper.SetInputConnection(xform.GetOutputPort());


            vtkActor gridActor = vtkActor.New();
            gridActor.SetMapper(gridMapper);
            gridActor.PickableOn();
            gridActor.SetTexture(texSun);

            m_vtkRenderer.AddActor(gridActor);
            //m_ActorDic.Add("gridActor", gridActor);








            //添加边框，为这个物体
            vtkOutlineFilter olFilter = vtkOutlineFilter.New();
            olFilter.SetInput(normal.GetOutput());

            vtkPolyDataMapper bMapper = vtkPolyDataMapper.New();
            bMapper.SetInput(olFilter.GetOutput());

            vtkActor bActor = vtkActor.New();
            bActor.SetMapper(bMapper);
            bActor.GetProperty().SetColor (0,0,0);
           


            m_vtkRenderer.AddActor(bActor);
           // m_ActorDic.Add("bAcotr", bActor);




            //vtkContourFilter cf = vtkContourFilter.New();
            //cf.SetInput(dem.GetOutput());

            //cf.SetValue(0, 100);
            //cf.SetValue(1, 200);
            //cf.SetValue(2, 300);
            //cf.SetValue(3, 400);
            //cf.SetValue(4, 500);






            // renWin.SetSize(250, 250);
            m_vtkRenderWindow .Render();
            vtkCamera camera = m_vtkRenderer.GetActiveCamera();
            camera.Zoom(1.5);


            // Create a text property for both cube axes
            vtkTextProperty tprop;
            tprop = vtkTextProperty.New();
            tprop.SetColor(0, 0, 0);
            tprop.ShadowOn();



            vtkCubeAxesActor2D axes;
            axes = vtkCubeAxesActor2D.New();
            axes.SetInput(m_warp.GetOutput());
            axes.SetCamera(m_vtkRenderer.GetActiveCamera());

            //axes.SetLabelFormat("%6.4g");
            axes.SetFlyModeToOuterEdges();
            axes.SetFontFactor(0.8);
            axes.SetAxisTitleTextProperty(tprop);
            axes.SetAxisLabelTextProperty(tprop);
            axes.SetNumberOfLabels(8);
            axes.SetLabelFormat("%8.1f");
            




            vtkAxisActor2D xA2 = axes.GetXAxisActor2D();
            xA2.SetNumberOfMinorTicks(1);

            vtkAxisActor2D zA2 = axes.GetZAxisActor2D();
            zA2.SetNumberOfLabels(3);




            m_vtkRenderer.AddViewProp(axes);



            vtkOrientationMarkerWidget omark = vtkOrientationMarkerWidget.New();
            omark.SetInteractor(m_vtkRenderWindow .GetInteractor());

            omark.SetOrientationMarker(gridActor);

            omark.SetEnabled(1);



            //vtkCutter cut = vtkCutter.New();
            //cut.SetInputConnection(xform.GetOutputPort ());
            //cut.SetNumberOfContours(10);
            





            TerrainData thelp = new TerrainData(m_vtkRenderer, org[0], org[1], org[2], demImage, m_spatialResolution, bounds, m_scalefactor, rows, cols, minHeight, maxHeight);

            return thelp;


        }
    }
}
